#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""
@Project : aimix
@File    : clip.py
@IDE     : PyCharm
@Author  : admin
@Date    : 2025/4/3 13:02
"""
import os
import tempfile

from moviepy.editor import VideoFileClip
from pydub import AudioSegment
from pydub.silence import detect_nonsilent
from datetime import datetime
from core.audio.extract_audio import extract_audio_from_video
from scenedetect import VideoManager, SceneManager
from scenedetect.detectors import ContentDetector
from concurrent.futures import ThreadPoolExecutor, as_completed

from core.video.processor import clip_video_by_moviepy
from utils.tools import parallel_run


def batch_clip_video(tasks: list, max_workers: int = 4, queue=None) -> list:
    """
    并行处理多个视频剪辑任务。
    :param tasks: 任务列表，每个元素是 (input_file, output_file, start_time, end_time)
    :param max_workers: 最大并发线程数
    :param queue:
    """
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        future_to_task = []
        res = []
        for task in tasks:
            if queue is not None:
                queue.put(1)
            future_to_task.append(executor.submit(clip_video_by_moviepy, *task))
        for future in as_completed(future_to_task):
            future.result()
            if queue is not None:
                queue.put(1)
        return res


################ 按照固定秒数分镜 ###############

def split_video_by_duration(input_file, output_folder, segment_duration, queue=None):
    """按照固定时长切割视频"""
    video = VideoFileClip(input_file)
    video_duration = video.duration
    print(f"Video duration: {video_duration} seconds")
    num_segments = int(video_duration // segment_duration) + (1 if video_duration % segment_duration != 0 else 0)
    tasks = []
    # 根据非静音段分割视频
    output_subfolder = datetime.now().strftime("%Y-%m-%d")
    output_subfolder_path = os.path.join(output_folder, output_subfolder, "固定时长分镜", os.path.basename(input_file).split('.')[0])
    os.makedirs(output_subfolder_path, exist_ok=True)
    for i in range(num_segments):
        start_time = i * segment_duration
        end_time = (i + 1) * segment_duration
        segment_name = os.path.join(output_subfolder_path, f"shot_{i}.mp4")
        tasks.append((input_file, segment_name, start_time, end_time))
    # 释放资源
    video.close()
    batch_clip_video(tasks, queue)


################ 按照固定镜头数分镜 ###############


def split_video_by_shots(input_file, output_folder, num_shots, queue=None):
    """按照镜头数量切割视频"""
    video = VideoFileClip(input_file)
    # 计算每个分镜的时长
    video_duration = video.duration  # 获取视频总时长
    shot_duration = video_duration / num_shots  # 每个分镜的时长
    tasks = []
    # 根据非静音段分割视频
    output_subfolder = datetime.now().strftime("%Y-%m-%d")
    output_subfolder_path = os.path.join(output_folder, output_subfolder, "固定镜头分镜", os.path.basename(input_file).split('.')[0])
    os.makedirs(output_subfolder_path, exist_ok=True)
    # 按照镜头数量切割视频
    for i in range(num_shots):
        start_time = i * shot_duration  # 每个分镜的起始时间
        end_time = (i + 1) * shot_duration  # 每个分镜的结束时间
        output_file = os.path.join(output_subfolder_path, f"shot_{i}.mp4")
        tasks.append((input_file, output_file, start_time, end_time))
    # 关闭视频对象，释放资源
    video.close()
    batch_clip_video(tasks, queue)


################ 按照口播分镜 ###############


def detect_silence(audio_file, silence_thresh=-40, min_silence_len=1000):
    # 加载音频
    if audio_file.endswith(".mp3"):
        audio = AudioSegment.from_mp3(audio_file)
    elif audio_file.endswith(".wav"):
        audio = AudioSegment.from_wav(audio_file)
    else:
        raise ValueError("Unsupported audio format")

    # 检测非静音部分
    nonsilent_parts = detect_nonsilent(
        audio,
        min_silence_len=min_silence_len,
        silence_thresh=silence_thresh
    )
    start = 0
    # 将非静音部分转换为起止时间（秒）
    silence_periods = []
    for start_ms, end_ms in nonsilent_parts:
        if (end_ms / 1000) - start < 1:
            continue
        silence_periods.append((start, end_ms / 1000))  # 转换为秒
        start = end_ms / 1000
    return silence_periods


def split_video_by_audio(input_video, output_folder, queue=None):
    audio_file = extract_audio_from_video(input_video, tempfile.gettempdir(), ".wav")
    # 获取音频中的非静音段
    silence_periods = detect_silence(audio_file)
    # 读取视频
    video = VideoFileClip(input_video)
    video_duration = video.duration

    tasks = []
    # 根据非静音段分割视频
    output_subfolder = datetime.now().strftime("%Y-%m-%d")
    output_subfolder_path = os.path.join(output_folder, output_subfolder, "口播分镜", os.path.basename(input_video).split('.')[0])
    os.makedirs(output_subfolder_path, exist_ok=True)

    for i, (start_time, end_time) in enumerate(silence_periods):
        if start_time >= video_duration:
            break

        output_file =os.path.join(output_subfolder_path, f"shot_{i}.mp4")
        tasks.append((input_video, output_file, start_time, end_time))
    # 清理临时音频文件
    os.remove(audio_file)
    video.close()
    batch_clip_video(tasks, queue)


################ 按照转场分镜 ###############

def split_video_by_transition(video_path, output_folder, threshold=0.5, queue=None):
    """
    使用 PySceneDetect 库检测视频的镜头切换，并返回分段的帧号范围列表。
    """
    # 初始化 VideoManager 和 SceneManager
    video_manager = VideoManager([video_path])
    scene_manager = SceneManager()
    scene_manager.add_detector(ContentDetector(threshold=threshold*60))

    # 获取视频的帧率
    video_manager.start()
    fps = video_manager.get_framerate()

    # 检测镜头切换
    scene_manager.detect_scenes(frame_source=video_manager)
    scene_list = scene_manager.get_scene_list()

    tasks = []
    for i, scene in enumerate(scene_list):
        start_frame = scene[0].get_frames()
        end_frame = scene[1].get_frames() - 1

        start_time = start_frame / fps
        end_time = end_frame / fps
        output_subfolder = datetime.now().strftime("%Y-%m-%d")
        output_subfolder_path = os.path.join(output_folder, output_subfolder, "转场分镜", os.path.basename(video_path).split('.')[0])
        os.makedirs(output_subfolder_path, exist_ok=True)

        output_file = os.path.join(output_subfolder_path, f"shot_{i}.mp4")
        tasks.append((video_path, output_file, start_time, end_time))

    video_manager.release()
    batch_clip_video(tasks, queue)


################ AI智能分镜 ###############

def clip_video_by_Ai(input_file, output_folder, threshold=30.0):
    # TODO: Ai 智能分镜
    pass


